
/**
 * 公司高级JAVA工程师的业务代码，高！实在是高！
 *
 */
@Service
public class StockUpResultServiceImpl{
    
    @Override
    public void updateCurrentResults(net.sf.json.JSONObject jsonObject) {
        Long hour = new Long(LinkUtils.getDateHour(null));
        Long ratingResultId;
        String ratingResultName;
        boolean empty = StringUtils.isNotEmpty(jsonObject);
        StockUpResult stockUpResult;
        if (empty) {
            ratingResultId = jsonObject.getLong("id");
            ratingResultName = jsonObject.getString("ratingSerialNum");
            stockUpResult = this.getBaseMapper().getStockUpResultByCreateTime();
            if (StringUtils.isNull(stockUpResult)) {
                return;
            }
        } else {
            jsonObject = remoteUtilService.queryNewRatingResult();
            ratingResultId = jsonObject.getLong("id");
            ratingResultName = jsonObject.getString("ratingSerialNum");
            if (StringUtils.isNull(jsonObject)) {
                return;
            }
            stockUpResult = new StockUpResult();
            stockUpResult.setResultNumber(getSerialNum());
            stockUpResult.setBelongHour(hour);
        }
        stockUpResult.setRatingResultId(ratingResultId);
        stockUpResult.setRatingResultName(ratingResultName);
        Map<String, String> ratingResultMap = remoteUtilService.queryNewRatingResultById(String.valueOf(ratingResultId));
        
        JSONObject params = new JSONObject();
        params.put("type", Constants.CPJJLX);
        AjaxResult seasonResult = remoteJctDictionService.listByType(params);
        List<JctDiction> jctDictions = JSON.parseArray(JSONObject.toJSON(seasonResult.get("data")).toString(), JctDiction.class);
        Map<String, String> seasonTypeCodeMap = new HashMap<>();
        for (JctDiction jctDiction : jctDictions) {
            seasonTypeCodeMap.put(String.valueOf(jctDiction.getIdKey()), jctDiction.getValue());
        }

        JctDiction jctDiction = new JctDiction();
        jctDiction.setTypeCode(Constants.SALE_CALCULATE_TOP_LEVEL);
        List<JctDiction> dictionList = remoteJctDictionService.getListByTypeCodeAndState(jctDiction);
        Map<String, String> dictionMap = new HashMap<>();
        for (JctDiction diction : dictionList) {
            dictionMap.put(String.valueOf(diction.getIdKey()), diction.getName());
        }
        Map<String, String> dictionTopMap = new HashMap<>();
        for (JctDiction diction : dictionList) {
            dictionTopMap.put(String.valueOf(Integer.parseInt(diction.getValue()) + 1), String.valueOf(diction.getIdKey()));
        }

        Map<String, String> topLevelMap = DictCache.getDictCache("topLevel");
 
    
        List<StockUpResultDetailsDTO> currentResults = commodityOdsMapper.getCurrentResults();
    
        List<Long> shopIds = new ArrayList<>(currentResults.stream().map(StockUpResultDetailsDTO::getShopId).collect(Collectors.toSet()));
 
        List<StockUpJpSkuInfo> details = commodityJcMapper.getJpSkuInfo();
   
     
        List<PurchaseInTransitVO> transits = remoteStockService.getPurchaseInTransitsByShopIds(shopIds);
      
        List<OpenPositionDTO> positions = remoteStockService.getOpenPositionsByShopIds(shopIds);
        
        Map<String, Double> categoryDeliveryDateMap = remoteStockService.getEstimatedDayBySku();
  
        Map<String, PublicSettingAvgDayTypeDTO> calculateDailyAverageMap = settingAvgDayTypeService.publicSettingAvgDayTypeMap();
        Set<String> calculateDailyAverageKeys = calculateDailyAverageMap.keySet();
   
        List<BasStorage> bbs = remoteStockService.selectBasStorageListByShopIds(shopIds);
       
        List<JSONObject> info = Collections.synchronizedList(new ArrayList<>());
        shopIds.stream().forEach(shopId -> {
            JSONObject json = new JSONObject();
            StringBuilder sb = new StringBuilder();
            bbs.stream().filter(bs -> Objects.equals(shopId, bs.getShopId()) && "本地仓库".equals(bs.getStorageSxNm()))
                    .forEach(bs -> {
                        sb.append("'" + bs.getParentId() + "-" + bs.getIdKey() + "',");
                    });
            String cw = sb.length() > 0 ? sb.substring(0, sb.length() - 1) : null;
            if (StringUtils.isNotBlank(cw)) {
                json.put("FilterStringSql", "FStockId.FNumber in (" + cw + ")");
                json = JSONObject.parseObject(remotePurchaseService.queryStkInventory(json.toJSONString()));
                Boolean flag = json.getBoolean("flag");
                if (flag != null && flag) {
                    JSONArray infoArray = json.getJSONArray("info");
                    info.addAll(infoArray.toJavaList(JSONObject.class));
                }
            }
        });
        Map<String, Map<String, Long>> stockMap = new ConcurrentHashMap<>();
        info.stream().forEach(cw -> {
            String warehouseId = String.valueOf(cw.getString("warehouse_id"));
            Map<String, Long> goodsSkuIdStockMap = LinkUtils.getNewMap(stockMap.get(warehouseId));
            String goodsSkuIdStr = cw.getString("goods_sku_id");
            Long stock = LinkUtils.getZeroLongNotNull(goodsSkuIdStockMap.get(goodsSkuIdStr));
            stock += cw.getLong("s_amounts");
            goodsSkuIdStockMap.put(goodsSkuIdStr, stock);
            stockMap.put(warehouseId, goodsSkuIdStockMap);
        });
       
        Map<String, Map<String, SalesBySellerSkuVO>> salesBySellerSkuMap = listSalesBySellerSku();
     
        Map<String, Map<String, SalesByOperationCodeVO>> SalesByOperationCodeSellerSkuYesterdayMap = listSalesByOperationCodeSellerSkuYesterday();
        Map<String, LongAdder> codeYesterdaySumMap = new ConcurrentHashMap<>();
        SalesByOperationCodeSellerSkuYesterdayMap.forEach((key, codeMap) -> {
            if (StringUtils.isNotNull(codeMap)) {
                String keyof = String.valueOf(key);
                LongAdder sum = new LongAdder();
                codeMap.values().stream().forEach(vo -> {
                    if (Objects.equals(keyof, vo.getOperationCode())) {
                        sum.add(vo.getSum());
                    }
                });
                codeYesterdaySumMap.put(keyof, sum);
            }
        });

        Map<String, Map<String, SalesByOperationCodeVO>> salesByOperationCodeMap = listSalesByOperationCode();
        Map<String, LongAdder> codeSumMap = new ConcurrentHashMap<>();
        salesByOperationCodeMap.forEach((key, codeMap) -> {
            if (StringUtils.isNotNull(codeMap)) {
                String keyof = String.valueOf(key);
                LongAdder sum = new LongAdder();
                codeMap.values().stream().forEach(vo -> {
                    if (Objects.equals(keyof, vo.getOperationCode())) {
                        sum.add(vo.getSum());
                    }
                });
                codeSumMap.put(keyof, sum);
            }
        });
     
        Map<String, Map<String, List<SalesByOperationCodeVO>>> salesByOperationCodeSellerSkuMap = listSalesByOperationCodeSellerSku();
        Comparator<SalesByOperationCodeVO> comparator = (v1, v2) -> Integer.compare(v2.getSum(), v1.getSum());
      
        Map<String, Map<String, SalesBySeason>> stringObjectMap = listBySeasonType();
      
        Map<String, Map<String, SalesByMonthAndOperationCode>> monthAndOperationCode = listByMonthAndOperationCode();
        
        Map<String, BigDecimal> stringBigDecimalMap = historyTopLevelService.selectHistoryTopLevelByOperationCodes();
        
        List<SaleLifecycleCurve> saleLifecycleCurves = saleLifecycleCurveService.selectSaleLifecycleCurveList();
        Map<String, Map<String, SaleLifecycleCurve>> periodTypeTopCurveMap = new HashMap<>();
        for (SaleLifecycleCurve curve : saleLifecycleCurves) {
            String periodType = curve.getPeriodType();
            Map<String, SaleLifecycleCurve> topCurveMap = LinkUtils.getNewMap(periodTypeTopCurveMap.get(periodType));
            topCurveMap.put(String.valueOf(curve.getTopLevelId()), curve);
            periodTypeTopCurveMap.put(periodType, topCurveMap);
        }
 
        Map<String, Map<String, Map<String, Long>>> combineScoreMap = comUpCombineScoreSetService.getCombineScoreMap();

        Map<String, Map<String, Long>> standardRevolveDayMap = stockUpStandardRevolveDaysService.queryStandardRevolveDay();
        Set<String> standardRevolveDayKeys = standardRevolveDayMap.keySet();
        String standardRevolveDayKey = standardRevolveDayKeys.stream().filter(key -> {
            String[] split = key.split(",");
            long startTime = LinkUtils.parseDay(split[0]).getTime();
            long endTime = LinkUtils.parseDay(split[1]).getTime();
            long time = System.currentTimeMillis();
            return startTime <= time && time <= endTime;
        }).findFirst().orElse(null);
        Map<String, Long> revolveDayMap = LinkUtils.getNewMap(standardRevolveDayMap.get(standardRevolveDayKey));
        Set<String> revolveDayKeys = revolveDayMap.keySet();
     
        Map<String, Map<String, Long>> outOfMap = stockUpSettingOutOfService.selectStockUpSettingOutOfMap();
        Set<String> outOfKeys = outOfMap.keySet();
    
        Map<String, String> seasonOutMap = stockUpSettingSeasonOutService.selectStockUpSettingSeasonOutMap();
        Map<String, String> topSeasonOutMap = new HashMap<>();
        for (String key : seasonOutMap.keySet()) {
            topSeasonOutMap.put(topLevelMap.get(key), seasonOutMap.get(key));
        }
        
       
        Map<String, Long> seasonMidMap = stockUpSettingSeasonMidService.selectStockUpSettingSeasonMidMap();
  
        Map<String, String> columnNameMap = remoteStockService.getOpcnCloumnNameMapByZero();
        OrderFormula fbaStockFormula = remoteStockService.selectOrderFormulaListByShopIdByZero(FbaStockFormula.FBA_STOCK);
        OrderFormula averageDailySalesFormula = remoteStockService.selectOrderFormulaListByShopIdByZero(AverageDailySalesFormula.AVERAGE_DAILY_SALES);
     
        Map<String, Map<String, String>> utilTopMap = remoteStockService.getUtilTopMap();
        Map<String, LongAdder> operationCodeAverageDailySalesWeightingMap = getOperationCodeAverageDailySalesWeighting(salesBySellerSkuMap);
      
        Map<String, Map<String, Map<String, Map<String, Map<String, String>>>>> colorSetMap = stockUpColorSettingService.getColorSetMap();
      
        Map<String, Map<String, Map<String, String>>> prepositionRollcallMap = stockUpPrepositionRollcallService.queryPrepositionRollcall();
       
        List<String> operationCodeTops = stockUpOperationCodeTopService.getOperationCodeList();

        Map<String, Long> courierDaysMap = stockUpInitLogisticsDaysService.getCourierDaysMap();
  
        currentResults = Collections.synchronizedList(currentResults);
        Map<String, LongAdder> codeDh30DaySumMap = new ConcurrentHashMap<>();
        currentResults.stream().forEach(dto -> {
            String operationCode = String.valueOf(dto.getOperationCode());
            String sellerSku = dto.getSellerSku();
            Long fulfillable = dto.getFulfillable();
            Long pendingOrders = Constants.ZERO_LONG;
            Map<String, SalesBySellerSkuVO> sellerSkuMap = LinkUtils.getNewMap(salesBySellerSkuMap.get(String.valueOf(dto.getShopId())));
            SalesBySellerSkuVO vo = sellerSkuMap.get(sellerSku);
            if (StringUtils.isNotNull(vo)) {
                pendingOrders = (long) vo.getOne();
            }
            int salesVolumeDay30Zr = Constants.ZERO;
            SalesByOperationCodeVO codeVO = LinkUtils.getNewMap(SalesByOperationCodeSellerSkuYesterdayMap.get(operationCode)).get(sellerSku);
            if (StringUtils.isNotNull(codeVO)) {
                salesVolumeDay30Zr = codeVO.getSum();
            }
            
            FormulaDTO fbaStockFormulaDTO = new FormulaDTO();
            fbaStockFormulaDTO.setFormula(fbaStockFormula.getFormula());
            fbaStockFormulaDTO.setColumnNameMap(columnNameMap);
            fbaStockFormulaDTO.setFbaStockFormula(new FbaStockFormula(dto.getInbound(), dto.getReserved(), fulfillable, dto.getReceiving(), pendingOrders));
            long fbaStock = remoteStockService.getColumnNameByFormula(fbaStockFormulaDTO).longValue();
            dto.setFbaStock(fbaStock);
            
            String operationCodeTop = operationCodeTops.stream().filter(code -> Objects.equals(code, operationCode)).findFirst().orElse(null);
            if (StringUtils.isNotBlank(operationCodeTop) && fbaStock - dto.getFbaIntransit() <= 0) {
                LongAdder longAdder = codeDh30DaySumMap.get(operationCode);
                if (StringUtils.isNull(longAdder)) {
                    longAdder = new LongAdder();
                }
                longAdder.add(salesVolumeDay30Zr);
                codeDh30DaySumMap.put(operationCode, longAdder);
            }
        });
        Calendar instance = Calendar.getInstance();
        int year = LinkUtils.getDateYear(instance);
        int month = LinkUtils.getDateMonth(instance);
        Map<String, DoubleAdder> codeCurrentTurnoverDaysMap = new ConcurrentHashMap<>();
        currentResults.stream().forEach(dto -> {
            Long shelfDay = dto.getShelfDay();
            Long shopId = dto.getShopId();
            String shopIdStr = String.valueOf(shopId);
            String operationCode = String.valueOf(dto.getOperationCode());
            BigDecimal topId = stringBigDecimalMap.get(operationCode);
            if (StringUtils.isNotNull(topId)) {
                dto.setTopHistory(dictionMap.get(topId.toString()));
            }
            
            boolean cxBoolean = false;
            boolean qdBoolean = false;
            Long goodsSkuId = dto.getGoodsSkuId();
            String goodsSkuIdStr = String.valueOf(goodsSkuId);
            StockUpJpSkuInfo detail = details.stream().filter(f -> Objects.equals(goodsSkuId, f.getGoodsSkuId())).findFirst().orElse(null);
           
            if (StringUtils.isNotNull(detail)) {
                String firstOrderDate = dto.getFirstOrderDate();
                String seasonTypeIdStr = String.valueOf(detail.getSeasonTypeId());
                cxBoolean = Objects.equals(Constants.CXK, seasonTypeCodeMap.get(seasonTypeIdStr));
                qdBoolean = Objects.equals(Constants.QDK, seasonTypeCodeMap.get(seasonTypeIdStr));
                
                if (Objects.equals(Constants.ZERO_STR, firstOrderDate)) {
                    dto.setNewOldType(Constants.ONE_STR);
                } else {
                    Date date = LinkUtils.parseDay(firstOrderDate);
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(date);
                    int firstOrderDateYear = LinkUtils.getDateYear(calendar);
                    if (cxBoolean && ((year - firstOrderDateYear == 1 && month == 12) || (firstOrderDateYear >= year))) {
                        dto.setNewOldType(Constants.ZERO_STR);
                    } else if (qdBoolean && (firstOrderDateYear == year)) {
                        dto.setNewOldType(Constants.ZERO_STR);
                    } else {
                        dto.setNewOldType(Constants.ONE_STR);
                    }
                }
                String colorIdStr = String.valueOf(detail.getColorId());
          
                SalesByOperationCodeVO vo = LinkUtils.getNewMap(salesByOperationCodeMap.get(operationCode)).get(colorIdStr);
                if (StringUtils.isNotNull(vo)) {
                    Long colorDay30 = (long) vo.getSum();
                    String seasonTypekey = cxBoolean ? Constants.ONE_STR : qdBoolean ? Constants.TWO_STR : Constants.THREE_STR;
                    String shelfDayKey = shelfDay <= 45 ? Constants.ONE_STR : Constants.TWO_STR;
                    colorSetMap.forEach((key, shopIdMap) -> {
                        if (StringUtils.isNotNull(shopIdMap)) {
                            Map<String, String> map = LinkUtils.getNewMap(LinkUtils.getNewMap(LinkUtils.getNewMap(shopIdMap.get(shopIdStr)).get(seasonTypekey)).get(shelfDayKey));
                            if (Objects.equals(Constants.ZERO_STR, key)) {
                                String colorKey = map.keySet().stream().filter(k -> {
                                    String[] split = k.split(",");
                                    return Long.parseLong(split[0]) <= colorDay30 && colorDay30 < Long.parseLong(split[1]);
                                }).findFirst().orElse(null);
                                if (StringUtils.isNotNull(colorKey)) {
                                    dto.setColorLevel(map.get(colorKey));
                                }
                            } else {
                                Double operationCodeSum = Constants.ONE_DOUBLE;
                                LongAdder longAdder = codeSumMap.get(operationCode);
                                if (StringUtils.isNotNull(longAdder)) {
                                    operationCodeSum = longAdder.doubleValue();
                                }
                                Double colorBl = colorDay30 / operationCodeSum * Constants.HUNDRED;
                                String colorKey = map.keySet().stream().filter(k -> {
                                    String[] split = k.split(",");
                                    return Double.parseDouble(split[0]) <= colorBl && colorBl < Double.parseDouble(split[1]);
                                }).findFirst().orElse(null);
                                if (StringUtils.isNotNull(colorKey)) {
                                    dto.setColorLevel(map.get(colorKey));
                                }
                            }
                        }
                    });
                    
                    dto.setColorDay30(colorDay30);
                }
                BeanUtils.copyProperties(detail, dto);
            } else {
                dto.setNewOldType(Constants.ONE_STR);
            }

            Map<String, String> topMap = LinkUtils.getNewMap(utilTopMap.get(shopIdStr));
            LongAdder longAdder = operationCodeAverageDailySalesWeightingMap.get(operationCode);
            if (StringUtils.isNull(longAdder)) {
                longAdder = new LongAdder();
            }
            long weighting = longAdder.longValue();
            
            Set<String> topKeys = topMap.keySet();
            String topKey = topKeys.stream().filter(key -> {
                String[] split = key.split(",");
                return Long.parseLong(split[0]) <= weighting && weighting < Long.parseLong(split[1]);
            }).findFirst().orElse(null);
            String top = topMap.get(topKey);
            dto.setTop(top);
            
    
            Long purchaseInTransit = Constants.ZERO_LONG;
            boolean skuTypeBoolean = Constants.ONE_STR.equals(dto.getSkuType());
            if (skuTypeBoolean) {
                PurchaseInTransitVO transit = transits.stream().filter(f -> Objects.equals(shopId, f.getShopId()) && Objects.equals(goodsSkuId, f.getGoodsSkuId())).findFirst().orElse(new PurchaseInTransitVO(Constants.ZERO_LONG));
                purchaseInTransit = transit.getSjAmounts();
            }
            dto.setPurchaseInTransit(purchaseInTransit);
      
            String sellerSku = dto.getSellerSku();
            OpenPositionDTO position = positions.stream().filter(f -> Objects.equals(shopId, f.getShopId()) && Objects.equals(sellerSku, f.getSellerSku())).findFirst().orElse(new OpenPositionDTO(Constants.ZERO_LONG));
            Long actualPackingAmounts = position.getActualPackingAmounts();
            dto.setActualPackingAmounts(actualPackingAmounts);
            //产品说的，如果拿到小数，就改成整数，用户正常不会写小数
            Double categoryDeliveryDate = categoryDeliveryDateMap.get(goodsSkuIdStr);
            dto.setCategoryDeliveryDate(StringUtils.isNotNull(categoryDeliveryDate) ? categoryDeliveryDate.longValue() : null);
            LongAdder localStockLong = new LongAdder();
            LongAdder overseasStockLong = new LongAdder();
            if (skuTypeBoolean) {
                bbs.stream().filter(bs -> Objects.equals(shopId, bs.getShopId()) && "本地仓库".equals(bs.getStorageSxNm())).forEach(storage -> {
                    Long stock = LinkUtils.getZeroLongNotNull(LinkUtils.getNewMap(stockMap.get(storage.getParentId() + "-" + storage.getIdKey())).get(goodsSkuIdStr));
                    String storageNm = storage.getStorageNm();
                    if (storageNm.contains(Constants.XIAMEN)) {
                        localStockLong.add(stock);
                    } else if (storageNm.contains(Constants.GUANGZOU)) {
                        localStockLong.add(stock);
                    } else if (storageNm.contains(Constants.OVERSEAS_GC)) {
                        overseasStockLong.add(stock);
                    } else if (storageNm.contains(Constants.OVERSEAS_GH)) {
                        overseasStockLong.add(stock);
                    } else if (storageNm.contains(Constants.OVERSEAS_JF)) {
                        overseasStockLong.add(stock);
                    } else if (storageNm.contains(Constants.OVERSEAS_ZY)) {
                        overseasStockLong.add(stock);
                    } else if (storageNm.contains(Constants.OVERSEAS_CS)) {
                        overseasStockLong.add(stock);
                    }
                });
            }
            long localStock = localStockLong.longValue();
            long overseasStock = overseasStockLong.longValue();
            dto.setLocalStock(localStock);
            dto.setOverseasStock(overseasStock);
            
            Long pendingOrders = Constants.ZERO_LONG;
            Long salesVolumeDay3 = Constants.ZERO_LONG;
            Long salesVolumeDay7 = Constants.ZERO_LONG;
            Long salesVolumeDay14 = Constants.ZERO_LONG;
            Long salesVolumeDay30 = Constants.ZERO_LONG;
            Map<String, SalesBySellerSkuVO> sellerSkuMap = LinkUtils.getNewMap(salesBySellerSkuMap.get(String.valueOf(shopId)));
            SalesBySellerSkuVO vo = sellerSkuMap.get(sellerSku);
            if (StringUtils.isNotNull(vo)) {
                pendingOrders = (long) vo.getOne();
                salesVolumeDay3 = (long) vo.getThree();
                salesVolumeDay7 = (long) vo.getSeven();
                salesVolumeDay14 = (long) vo.getFourteen();
                salesVolumeDay30 = (long) vo.getThirty();
            }
            Long reserved = dto.getReserved();
            Long fulfillable = dto.getFulfillable();
            dto.setAmazonStock(reserved + fulfillable - pendingOrders);
            
            Long fbaStock = dto.getFbaStock();
            
            dto.setSalesVolumeDay30(salesVolumeDay30);
            Double averageDailySalesDay3 = Double.parseDouble(Constants.DF_2.format(salesVolumeDay3 / 3.0));
            Double averageDailySalesDay7 = Double.parseDouble(Constants.DF_2.format(salesVolumeDay7 / 7.0));
            Double averageDailySalesDay14 = Double.parseDouble(Constants.DF_2.format(salesVolumeDay14 / 14.0));
            Double averageDailySalesDay30 = Double.parseDouble(Constants.DF_2.format(salesVolumeDay30 / 30.0));
            dto.setAverageDailySalesDay3(averageDailySalesDay3);
            dto.setAverageDailySalesDay7(averageDailySalesDay7);
            dto.setAverageDailySalesDay14(averageDailySalesDay14);
            dto.setAverageDailySalesDay30(averageDailySalesDay30);
            Long averageDailySalesWeighting = LinkUtils.getBigDecimalRoundHalfUpByDoubleToLong((averageDailySalesDay3 + averageDailySalesDay7 + averageDailySalesDay14) / 3.0);
            dto.setAverageDailySalesWeighting(averageDailySalesWeighting);
            
            FormulaDTO averageDailySalesFormulaDTO = new FormulaDTO();
            averageDailySalesFormulaDTO.setFormula(averageDailySalesFormula.getFormula());
            averageDailySalesFormulaDTO.setColumnNameMap(columnNameMap);
            averageDailySalesFormulaDTO.setAverageDailySalesFormula(new AverageDailySalesFormula(salesVolumeDay3, salesVolumeDay7, salesVolumeDay14, salesVolumeDay30));
            Double averageDailySales = remoteStockService.getColumnNameByFormula(averageDailySalesFormulaDTO);
            dto.setAverageDailySales(averageDailySales);
            
            Long allStock = fbaStock + localStock + purchaseInTransit + actualPackingAmounts + overseasStock;
            dto.setAllStock(allStock);
            
            PublicSettingAvgDayTypeDTO dayTypeDTO = calculateDailyAverageMap.get(calculateDailyAverageKeys.stream().filter(key -> {
                String[] split = key.split(",");
                return Long.parseLong(split[0]) <= shelfDay && shelfDay <= Long.parseLong(split[1]);
            }).findFirst().orElse(null));
            Long calculateDailyAverageNum = null;
            if (StringUtils.isNotNull(dayTypeDTO)) {
                dto.setCalculateDailyAverageId(dayTypeDTO.getId());
                dto.setCalculateDailyAverageNm(dayTypeDTO.getTypeName());
                JEP jep = new JEP();
                jep.addStandardFunctions();
                jep.addVariable("salesVolumeDay3", salesVolumeDay3);
                jep.addVariable("salesVolumeDay7", salesVolumeDay7);
                jep.addVariable("salesVolumeDay14", salesVolumeDay14);
                jep.addVariable("salesVolumeDay30", salesVolumeDay30);
                jep.addVariable("averageDailySales", averageDailySales);
                jep.addVariable("averageDailySalesDay3", averageDailySalesDay3);
                jep.addVariable("averageDailySalesDay7", averageDailySalesDay7);
                jep.addVariable("averageDailySalesDay14", averageDailySalesDay14);
                jep.addVariable("averageDailySalesDay30", averageDailySalesDay30);
                jep.parseExpression(dayTypeDTO.getFormulaValue());
                calculateDailyAverageNum = LinkUtils.getBigDecimalRoundHalfUpByDoubleNaNToLong(jep.getValue());
            }
            dto.setCalculateDailyAverageNum(calculateDailyAverageNum);
            
            String categoryLabel = null;
            String operationCodeTop = operationCodeTops.stream().filter(code -> Objects.equals(code, operationCode)).findFirst().orElse(null);
            if (StringUtils.isNotBlank(operationCodeTop)) {
                LongAdder dh30DaySum = codeDh30DaySumMap.get(operationCode);
                LongAdder codeSum = codeYesterdaySumMap.get(operationCode);
                if (StringUtils.isNotNull(codeSum) && StringUtils.isNotNull(dh30DaySum) && dh30DaySum.longValue() / codeSum.doubleValue() >= 0.4) {
                    categoryLabel = "";
                }
            }
            
            if (StringUtils.isBlank(categoryLabel)) {
                if (Objects.equals("", dto.getStyleType())) {
                    categoryLabel = "";
                } else if (StringUtils.isNotNull(categoryDeliveryDate) && categoryDeliveryDate > 9) {
                    boolean topBoolean = Objects.equals(Constants.ONE_STR, top) || Objects.equals(Constants.TWO_STR, top);
                    if ((cxBoolean && ((topBoolean && 3 <= month && month <= 6) || (!topBoolean && 3 <= month && month <= 4)))
                            || (qdBoolean && ((topBoolean && 9 <= month && month <= 12) || (!topBoolean && 9 <= month && month <= 10)))) {
                        categoryLabel = "";
                    }
                }
            }
            if (StringUtils.isBlank(categoryLabel)) {
                categoryLabel = "";
            }
            dto.setCategoryLabel(categoryLabel);
            
        
            String attribute = dto.getInventoryAttribute();
            boolean inventoryAttributeBoolean = Objects.equals(Constants.QCK, attribute) || Objects.equals(Constants.PSQC, attribute);
            String topHistory = dto.getTopHistory();
            String colorIdStr = String.valueOf(dto.getColorId());
            Long stockQuantityFront = Constants.ZERO_LONG;
            if (!inventoryAttributeBoolean && StringUtils.isNotNull(operationCode)) {
                Map<String, Map<String, String>> fjMap = prepositionRollcallMap.get(operationCode);
                if (StringUtils.isNull(fjMap)) {
                    stockQuantityFront = Constants.ZERO_LONG;
                } else {
                    for (Map.Entry<String, Map<String, String>> entry : fjMap.entrySet()) {
                        Map<String, String> value = entry.getValue();
                        String key = entry.getKey();
                        dto.setAntiSeason(key);
                        if (StringUtils.isNotNull(value)) {
                            if (Objects.equals(Constants.TWO_STR, key)) {
                                Long jzDay = seasonMidMap.get(String.valueOf(month));
                                if (StringUtils.isNull(jzDay)) {
                                    jzDay = Constants.ZERO_LONG;
                                }
                                List<SalesByOperationCodeVO> codeVos = LinkUtils.getNewMap(salesByOperationCodeSellerSkuMap.get(operationCode)).get(String.valueOf(colorIdStr));
                                if (StringUtils.isNotEmpty(codeVos)) {
                                    Collections.sort(codeVos, comparator);
                                    Long codeVoSize = LinkUtils.getRoundUpMultiply(new BigDecimal(codeVos.size()), 0.7);
                                    for (int i = 0; i < codeVoSize; i++) {
                                        if (Objects.equals(operationCode, codeVos.get(i).getOperationCode())) {
                                            stockQuantityFront = averageDailySalesWeighting * jzDay;
                                            break;
                                        }
                                    }
                                }
                            } else {
                                List<Integer> months = LinkUtils.getIntegerList(topSeasonOutMap.get(topHistory));
                                if (StringUtils.isNotEmpty(months)) {
                              
                                    double sum = 0;
                                    StringBuilder stockMonth = new StringBuilder();
                                    for (int m : months) {
                                        stockMonth.append(m + ",");
                                    }
                                    dto.setStockMonth(stockMonth.length() > 0 ? stockMonth.substring(0, stockMonth.length() - 1) : null);
                                    SalesBySeason season;
                                    if (qdBoolean) {
                                        season = LinkUtils.getNewMap(stringObjectMap.get(Constants.ONE_STR)).get(operationCode + ":" + sellerSku);
                                    } else {
                                        season = LinkUtils.getNewMap(stringObjectMap.get(Constants.ZERO_STR)).get(operationCode + ":" + sellerSku);
                                    }
                                    if (StringUtils.isNotNull(season)) {
                                        double b = season.getRate();
                                        for (String referenceLabel : value.keySet()) {
                                            if (Objects.equals(Constants.TWO_STR, referenceLabel)) {
                                                for (int m : months) {
                                                    SalesByMonthAndOperationCode sales = LinkUtils.getNewMap(monthAndOperationCode.get(operationCode)).get(String.valueOf(m));
                                                    if (StringUtils.isNotNull(sales)) {
                                                        sum += sales.getSum() * b;
                                                    }
                                                }
                                            } else {
                                                Map<String, SaleLifecycleCurve> topCurveMap = null;
                                                if (cxBoolean) {
                                                    topCurveMap = periodTypeTopCurveMap.get(Constants.XCX);
                                                } else if (qdBoolean) {
                                                    topCurveMap = periodTypeTopCurveMap.get(Constants.XQD);
                                                }
                                                SaleLifecycleCurve curve = LinkUtils.getNewMap(topCurveMap).get(dictionTopMap.get(value.get(referenceLabel)));
                                                if (StringUtils.isNotNull(curve)) {
                                                    for (int m : months) {
                                                        double a = 0;
                                                        int day = LinkUtils.getDaysOfMonth(year, m, Constants.ONE);
                                                        switch (m) {
                                                            case 1:
                                                                a = Double.parseDouble(curve.getJanuaryNumber());
                                                                break;
                                                            case 2:
                                                                a = Double.parseDouble(curve.getFebruaryNumber());
                                                                break;
                                                            case 3:
                                                                a = Double.parseDouble(curve.getMarchNumber());
                                                                break;
                                                            case 4:
                                                                a = Double.parseDouble(curve.getAprilNumber());
                                                                break;
                                                            case 5:
                                                                a = Double.parseDouble(curve.getMayNumber());
                                                                break;
                                                            case 6:
                                                                a = Double.parseDouble(curve.getJuneNumber());
                                                                break;
                                                            case 7:
                                                                a = Double.parseDouble(curve.getJulyNumber());
                                                                break;
                                                            case 8:
                                                                a = Double.parseDouble(curve.getAugustNumber());
                                                                break;
                                                            case 9:
                                                                a = Double.parseDouble(curve.getSeptemberNumber());
                                                                break;
                                                            case 10:
                                                                a = Double.parseDouble(curve.getOctoberNumber());
                                                                break;
                                                            case 11:
                                                                a = Double.parseDouble(curve.getNovemberNumber());
                                                                break;
                                                            case 12:
                                                                a = Double.parseDouble(curve.getDecemberNumber());
                                                                break;
                                                        }
                                                        sum += a * day * b;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    stockQuantityFront = LinkUtils.doubleToLong(sum - allStock);
                                }
                            }
                        }
                    }
                }
            }
            if (stockQuantityFront < 5) {
                stockQuantityFront = Constants.ZERO_LONG;
            } else {
                stockQuantityFront = LinkUtils.getRoundUpDivide(new BigDecimal(stockQuantityFront), 5.0) * 5;
            }
            dto.setStockQuantityFront(stockQuantityFront);
            
        
            Long stockQuantityRoutine = Constants.ZERO_LONG;
            String colorLevel = dto.getColorLevel();
      
            if (Objects.equals(Constants.ZERO_LONG, averageDailySalesWeighting)) {
                averageDailySalesWeighting = Constants.ONE_LONG;
            }
            
        
            if (StringUtils.isNotNull(calculateDailyAverageNum) && !inventoryAttributeBoolean) {
             
                Long num = calculateDailyAverageNum;
                if (Objects.equals(Constants.ZERO_LONG, num)) {
                    num = Constants.ONE_LONG;
                }
                Double currentTurnoverDays = allStock * Constants.ONE_DOUBLE / num;
                if (currentTurnoverDays < 80) {
                    DoubleAdder doubleAdder = codeCurrentTurnoverDaysMap.get(operationCode);
                    if (StringUtils.isNull(doubleAdder)) {
                        doubleAdder = new DoubleAdder();
                    }
                    doubleAdder.add((80 - currentTurnoverDays) * calculateDailyAverageNum);
                    codeCurrentTurnoverDaysMap.put(operationCode, doubleAdder);
                }
                dto.setCurrentTurnoverDays(currentTurnoverDays);
                if (shelfDay > 25) {
                    Long fraction;
                    Map<String, Map<String, Long>> topZhMap = LinkUtils.getNewMap(combineScoreMap.get(Constant.TOP_LEVEL_VALUE));
                    Map<String, Map<String, Long>> colorZhMap = LinkUtils.getNewMap(combineScoreMap.get(Constant.COLOR_LEVEL_VALUE));
                    String code;
                    if (shelfDay <= 45) {
                        code = SalesPeriod.NEW_PRODUCT_PROTECTION_PERIOD.getCode();
                    } else {
                        code = SalesPeriod.DAILY_SALES_PERIOD.getCode();
                    }
                    Map<String, Long> topFsMap = LinkUtils.getNewMap(topZhMap.get(code));
                    Map<String, Long> colorFsMap = LinkUtils.getNewMap(colorZhMap.get(code));
                    Long topFs = topFsMap.get(top);
                    Long colorFs = colorFsMap.get(colorLevel);
                    if (StringUtils.isNull(topFs) || StringUtils.isNull(colorFs)) {
                        fraction = Constants.ZERO_LONG;
                    } else {
                        fraction = topFs * colorFs;
                    }
                    String revolveDayKey = revolveDayKeys.stream().filter(key -> {
                        String[] split = key.split(",");
                        return Long.parseLong(split[0]) <= fraction && fraction <= Long.parseLong(split[1]);
                    }).findFirst().orElse(null);
                    Long turnoverDays = LinkUtils.getZeroLongNotNull(revolveDayMap.get(revolveDayKey));
                    if (currentTurnoverDays >= turnoverDays) {
                        stockQuantityRoutine = Constants.ZERO_LONG;
                    } else {
                        boolean klxBoolean = false;
                        if (Objects.equals("", categoryLabel)) {
                            String outOfKey = outOfKeys.stream().filter(key -> {
                                String[] split = key.split(",");
                                return Long.parseLong(split[0]) <= month && month <= Long.parseLong(split[1]);
                            }).findFirst().orElse(null);
                            Map<String, Long> dhMap = LinkUtils.getNewMap(outOfMap.get(outOfKey));
                            if (StringUtils.isNotEmpty(dhMap)) {
                                if (StringUtils.isNull(categoryDeliveryDate)) {
                                    categoryDeliveryDate = 9.0;
                                }
                                Long kdDay = courierDaysMap.get(String.valueOf(dto.getDeptId()));
                                if (StringUtils.isNull(kdDay)) {
                                    kdDay = 8L;
                                }
                                Double dhDay = categoryDeliveryDate + kdDay - (overseasStock + fbaStock) * Constants.ZERO_DOUBLE / averageDailySalesWeighting;
                                String key;
                                if (dhDay < 15) {
                                    key = Constants.ONE_STR;
                                } else {
                                    key = Constants.TWO_STR;
                                }
                                Long dh = dhMap.get(key);
                                if (StringUtils.isNotNull(dh)) {
                                    stockQuantityRoutine = LinkUtils.doubleToLong((dh - currentTurnoverDays) * averageDailySalesWeighting);
                                } else {
                                    klxBoolean = true;
                                }
                            } else {
                                klxBoolean = true;
                            }
                        } else if (Objects.equals("", categoryLabel)) {
                            stockQuantityRoutine = LinkUtils.doubleToLong((turnoverDays - currentTurnoverDays - 5) * calculateDailyAverageNum);
                        } else if (Objects.equals("", categoryLabel)) {
                            if (StringUtils.isNull(categoryDeliveryDate)) {
                                categoryDeliveryDate = 9.0;
                            }
                            stockQuantityRoutine = LinkUtils.doubleToLong((turnoverDays - currentTurnoverDays + categoryDeliveryDate - 9) * calculateDailyAverageNum);
                        } else {
                            klxBoolean = true;
                        }
                        if (klxBoolean) {
                            stockQuantityRoutine = LinkUtils.doubleToLong((turnoverDays - currentTurnoverDays) * calculateDailyAverageNum);
                        }
                    }
                }
            }
            if (stockQuantityRoutine < 5) {
                stockQuantityRoutine = Constants.ZERO_LONG;
            } else {
                stockQuantityRoutine = LinkUtils.getRoundUpDivide(new BigDecimal(stockQuantityRoutine), 5.0) * 5;
            }
            dto.setStockQuantityRoutine(stockQuantityRoutine);
            
            dto.setAvailableDay(LinkUtils.getBigDecimalRoundHalfUpByDoubleToLong(allStock * Constants.ONE_DOUBLE / averageDailySalesWeighting));
            dto.setFbaStockDay(LinkUtils.getBigDecimalRoundHalfUpByDoubleToLong(fbaStock * Constants.ONE_DOUBLE / averageDailySalesWeighting));
            
            
        });

        List<StockUpResultDetails> detailsList = Collections.synchronizedList(new ArrayList<>());
        List<StockUpResultDetailsDy> detailsDyList = Collections.synchronizedList(new ArrayList<>());
        currentResults.stream().forEach(dto -> {
            String operationCode = String.valueOf(dto.getOperationCode());
            Long shelfDay = dto.getShelfDay();
            Double currentTurnoverDays = dto.getCurrentTurnoverDays();
            Long calculateDailyAverageNum = dto.getCalculateDailyAverageNum();
            Long averageDailySalesWeighting = dto.getAverageDailySalesWeighting();
            Long stockQuantityRoutine = dto.getStockQuantityRoutine();
            Long stockQuantityFront = dto.getStockQuantityFront();
            Long allStock = dto.getAllStock();
         
            if (StringUtils.isNotNull(calculateDailyAverageNum) && StringUtils.isNotNull(shelfDay) && StringUtils.isNotNull(currentTurnoverDays) && shelfDay <= 25 && currentTurnoverDays < 80) {
                DoubleAdder doubleAdder = codeCurrentTurnoverDaysMap.get(operationCode);
                if (StringUtils.isNull(doubleAdder)) {
                    doubleAdder = new DoubleAdder();
                }
                double y = doubleAdder.doubleValue();
                double x = 0;
                String bwpz = ratingResultMap.get(operationCode);
                if (Objects.equals("", bwpz)) {
                    if (y > 1500) {
                        x = (y - 1500) * (80 - currentTurnoverDays) * calculateDailyAverageNum / y;
                    }
                } else if (Objects.equals("", bwpz)) {
                    if (y > 1000) {
                        x = (y - 1000) * (80 - currentTurnoverDays) * calculateDailyAverageNum / y;
                    }
                } else if (Objects.equals("", bwpz)) {
                    if (y > 800) {
                        x = (y - 800) * (80 - currentTurnoverDays) * calculateDailyAverageNum / y;
                    }
                } else {
                    x = (80 - currentTurnoverDays) * calculateDailyAverageNum;
                }
                stockQuantityRoutine = LinkUtils.doubleToLong((80 - currentTurnoverDays) * calculateDailyAverageNum - x);
                if (stockQuantityRoutine < 5) {
                    stockQuantityRoutine = Constants.ZERO_LONG;
                } else {
                    stockQuantityRoutine = LinkUtils.getRoundUpDivide(new BigDecimal(stockQuantityRoutine), 5.0) * 5;
                }
                dto.setStockQuantityRoutine(stockQuantityRoutine);
            }
            Long stockQuantityAll = stockQuantityRoutine + stockQuantityFront;
            dto.setStockQuantityAll(stockQuantityAll);
            Long cpfrAllStock = allStock + stockQuantityAll;
            dto.setCpfrAllStock(cpfrAllStock);
         
            if (StringUtils.isNull(calculateDailyAverageNum) || Objects.equals(Constants.ZERO_LONG, calculateDailyAverageNum)) {
                calculateDailyAverageNum = Constants.ONE_LONG;
            }
            dto.setCpfrDay(LinkUtils.getBigDecimalRoundHalfUpByDoubleToLong(stockQuantityAll * Constants.ONE_DOUBLE / calculateDailyAverageNum));
           
            if (Objects.equals(Constants.ZERO_LONG, averageDailySalesWeighting)) {
                averageDailySalesWeighting = Constants.ONE_LONG;
            }
            dto.setCpfrAvailableDay(LinkUtils.getBigDecimalRoundHalfUpByDoubleToLong(cpfrAllStock * Constants.ONE_DOUBLE / averageDailySalesWeighting));
            
            StockUpResultDetails stockUpResultDetails = new StockUpResultDetails();
            StockUpResultDetailsDy stockUpResultDetailsDy = new StockUpResultDetailsDy();
            BeanUtils.copyProperties(dto, stockUpResultDetails);
            BeanUtils.copyProperties(dto, stockUpResultDetailsDy);
            detailsList.add(stockUpResultDetails);
            detailsDyList.add(stockUpResultDetailsDy);
        });
     
        installALL(empty, stockUpResult, detailsList, detailsDyList);
    }
    
  
}
